<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0083: Notebook VII – A Snoot Full of Signals | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0083: Notebook VII – A Snoot Full of Signals" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="This GTK Tutorial covers Notebook signals." />
<meta property="og:description" content="This GTK Tutorial covers Notebook signals." />
<link rel="canonical" href="http://localhost:4000/posts/0083-notebook-vii-notebook-all-signals.html" />
<meta property="og:url" content="http://localhost:4000/posts/0083-notebook-vii-notebook-all-signals.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-10-29T00:00:00-04:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0083: Notebook VII – A Snoot Full of Signals" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2019-10-29T00:00:00-04:00","datePublished":"2019-10-29T00:00:00-04:00","description":"This GTK Tutorial covers Notebook signals.","headline":"0083: Notebook VII – A Snoot Full of Signals","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0083-notebook-vii-notebook-all-signals.html"},"url":"http://localhost:4000/posts/0083-notebook-vii-notebook-all-signals.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/container.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2019-10-29T00:00:00-04:00" itemprop="datePublished">Tuesday, October 29, 2019
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0083-notebook-vii--a-snoot-full-of-signals">0083: Notebook VII – A Snoot Full of Signals</h1>

<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/014_container/container_18.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/014_container/container_18_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/014_container/container_18_notebook_all_signals.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screen shots on a single page -->

<p>This time around, we’ll just reuse the same code we looked at last time, but with more signals hooked up. So, let’s look at what we have.</p>

<h2 id="in-the-constructor">In the Constructor</h2>

<p>The <code class="language-plaintext highlighter-rouge">Notebook</code> constructor gets a bit crowded:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">css</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CSS</span><span class="p">(</span><span class="n">getStyleContext</span><span class="p">());</span>

	<span class="n">TabTextView</span> <span class="n">tabTextView</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TabTextView</span><span class="p">();</span>
	<span class="n">Label</span> <span class="n">label</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Label</span><span class="p">(</span><span class="s">"Tab "</span> <span class="p">~</span> <span class="n">_lastPageNumber</span><span class="p">.</span><span class="n">to</span><span class="p">!</span><span class="nb">string</span><span class="p">());</span>
	<span class="n">appendPage</span><span class="p">(</span><span class="n">tabTextView</span><span class="p">,</span> <span class="n">label</span><span class="p">);</span>
	<span class="n">setTabReorderable</span><span class="p">(</span><span class="n">tabTextView</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>

	<span class="n">popupEnable</span><span class="p">();</span>
		
	<span class="n">addOnSwitchPage</span><span class="p">(&amp;</span><span class="n">onSwitchPage</span><span class="p">);</span>
	<span class="n">addOnPageRemoved</span><span class="p">(&amp;</span><span class="n">onPageRemoved</span><span class="p">);</span>
	<span class="n">addOnPageReordered</span><span class="p">(&amp;</span><span class="n">onPageReordered</span><span class="p">);</span>
	<span class="n">addOnPageAdded</span><span class="p">(&amp;</span><span class="n">onPageAdded</span><span class="p">);</span>

	<span class="n">addOnMoveFocusOut</span><span class="p">(&amp;</span><span class="n">onMoveFocusOut</span><span class="p">);</span> <span class="c1">// key-binding signals //</span>
	<span class="n">addOnChangeCurrentPage</span><span class="p">(&amp;</span><span class="n">onChangeCurrentPage</span><span class="p">);</span>
	<span class="n">addOnReorderTab</span><span class="p">(&amp;</span><span class="n">onReorderTab</span><span class="p">);</span>
	<span class="n">addOnSelectPage</span><span class="p">(&amp;</span><span class="n">onSelectPage</span><span class="p">);</span>
	<span class="n">addOnFocusTab</span><span class="p">(&amp;</span><span class="n">onFocusTab</span><span class="p">);</span>

<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>You’ll notice that the signals are hooked up in two groups:</p>

<ul>
  <li>the first group is for mouse-oriented actions, and</li>
  <li>the second is for keyboard shortcuts only.</li>
</ul>

<p>Most of the callbacks included here do no more than identify the signal that was triggered and report which page/tab is current, so there’s no point in going over them in detail. Instead, let’s look at what actions trigger those signals. Here’s a list:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Insert Page</code> Button: <code class="language-plaintext highlighter-rouge">onPageAdded</code> (no explanation needed),</li>
  <li><code class="language-plaintext highlighter-rouge">Remove Page</code> Button: <code class="language-plaintext highlighter-rouge">onSwitchPage</code> (because the page is removed, a new page becomes the current page),</li>
  <li><code class="language-plaintext highlighter-rouge">Tab</code> key: <em>NO SIGNAL</em> (moves from one widget to the next),</li>
  <li><code class="language-plaintext highlighter-rouge">Ctrl-Page Down</code>/<code class="language-plaintext highlighter-rouge">Ctrl-Page Up</code>: <code class="language-plaintext highlighter-rouge">onChangeCurrentPage</code> AND <code class="language-plaintext highlighter-rouge">onSwitchPage</code> are both triggered (these key combinations move from page to page, forward or backward), and</li>
  <li><code class="language-plaintext highlighter-rouge">Alt-Left Arrow</code>/<code class="language-plaintext highlighter-rouge">Alt-Right Arrow</code>: <code class="language-plaintext highlighter-rouge">onReorderTab</code> AND <code class="language-plaintext highlighter-rouge">onPageReordered</code> (moves the selected tab left or right)</li>
</ul>

<p>The signals I didn’t witness being triggered are:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">onSelectPage</code>, and</li>
  <li><code class="language-plaintext highlighter-rouge">onFocusTab</code>.</li>
</ul>

<p>I’m sure these get triggered somehow and their names do have certain implications. However, after digging around for a few hours and seeing no sign of them reacting to any action I took, I just moved on.</p>

<h2 id="bonus-the-popup-tab-menu">Bonus: the Popup Tab Menu</h2>

<p>You may have noticed this statement in the middle of the <code class="language-plaintext highlighter-rouge">MyNotebook</code> constructor:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">popupEnable</span><span class="p">();</span>
</code></pre></div></div>

<p>So innocuous sitting there, but it gives us one more bit of functionality. Right-click on any tab and you’re presented with a list of all the tabs in your application which will come in handy if ever we have so many tabs open that they stretch beyond the <code class="language-plaintext highlighter-rouge">Window</code>’s visible area. If we leave things the way they are now and keep adding tabs, the window will get wider to accomodate them all. And that means we’ve got one more thing to look at…</p>

<h2 id="how-to-manage-an-overabundance-of-tabs">How to Manage an Overabundance of Tabs</h2>

<p>That’s the second statement right below the one that turns on the popup menu:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">setScrollable</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
</code></pre></div></div>

<p>It’s that simple. Set to true, we get horizontal scrolling which means once the window’s width is taken up with tabs, it no longer grows in size each time we add a new one.</p>

<h2 id="conclusion">Conclusion</h2>

<p>We aren’t done with the <em>GTK</em> <code class="language-plaintext highlighter-rouge">Notebook</code>. Next time around, we’ll dive into how to identify and communicate with child widgets in a Notebook and look at a quick-n-dirty way to change the text label for a tab.</p>

<p>Until then, happy coding.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0082-notebook-vi-add-remove-tabs.html">Previous: Notebook VI - Add and Remove Tabs</a>
	</div>
	<div style="float: right;">
		<a href="./0084-notebook-viii-child-widgets.html">Next: Notebook VIII - Child Widgets</a>
	</div>
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0083-notebook-vii-notebook-all-signals.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
